/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.factory.server.rest;

import com.factory.server.dto.UserDTO;
import com.factory.server.dto.UserTasksWrapper;
import com.factory.server.dto.UsersWrapper;
import com.factory.server.json.SchedulerResult;
import com.factory.server.json.Plan;
import com.factory.server.json.Problem;
import com.factory.server.json.Stats;
import com.factory.server.service.FactoryServiceIface;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.ResponseBuilder;
import javax.ws.rs.core.Response.Status;
import org.hibernate.exception.ConstraintViolationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * Provides all web services to clients.
 * @author milos
 */
@Component
@Path("factory")
public class FactoryREST {

    @Autowired
    private FactoryServiceIface factoryService;

    @Path("fileUpload")
    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    public String putFile(@HeaderParam("name") String name, @HeaderParam("passwordHash") String passwordHash, Problem problem) {
        String role = factoryService.authorize(new UserDTO(name, null, passwordHash, false, false));
        if (!role.equals("USER") && !role.equals("ADMIN")) {
            throw new WebApplicationException(Response.status(401).
                    entity("Non auhtorized!").type("text/plain").build());
        }

        return factoryService.fileUpload(problem.getUserId(), problem.getAlgorithmicProblem(), problem.getLinesList(), problem.getParameters());
    }

    @GET
    @Path("/schedulerResult/{inputId}/")
    @Produces(MediaType.APPLICATION_JSON)
    public SchedulerResult getSchedulerResult(@HeaderParam("name") String name, @HeaderParam("passwordHash") String passwordHash, @PathParam("inputId") String inputId) {
        String role = factoryService.authorize(new UserDTO(name, null, passwordHash, false, false));
        if (!role.equals("USER") && !role.equals("ADMIN")) {
            throw new WebApplicationException(Response.status(401).
                    entity("Non auhtorized!").type("text/plain").build());
        }
        return factoryService.getSchedulerResult(inputId);
    }

    @GET
    @Path("/getResultFile/{inputId}/")
    @Produces(MediaType.APPLICATION_OCTET_STREAM)
    public Response getResult(@HeaderParam("name") String name, @HeaderParam("passwordHash") String passwordHash, @PathParam("inputId") String inputId) {
        String role = factoryService.authorize(new UserDTO(name, null, passwordHash, false, false));
        if (!role.equals("USER") && !role.equals("ADMIN")) {
            throw new WebApplicationException(Response.status(401).
                    entity("Non auhtorized!").type("text/plain").build());
        }

        ResponseBuilder builder = Response.status(Status.OK);
        builder.header("inputId", inputId);
        ByteArrayOutputStream resultStream = factoryService.getResultFile(inputId);
        if (resultStream != null) {
            builder.entity(resultStream.toByteArray());
            return builder.build();
        } else {
            return builder.entity(new ByteArrayOutputStream()).build();
        }
    }

    @POST
    @Path("/runFactory/")
    @Consumes(MediaType.APPLICATION_JSON)
    public Response runFactory(@HeaderParam("name") String name, @HeaderParam("passwordHash") String passwordHash, Plan plan) throws IOException {
        String role = factoryService.authorize(new UserDTO(name, null, passwordHash, false, false));
        if (!role.equals("USER") && !role.equals("ADMIN")) {
            throw new WebApplicationException(Response.status(401).
                    entity("Non auhtorized!").type("text/plain").build());
        }

        factoryService.registerPlan(plan);
        return Response.ok().build();
    }

    @POST
    @Path("/register/")
    @Consumes(MediaType.APPLICATION_JSON)
    public Response register(UserDTO userDTO) throws IOException {
        try {
            factoryService.register(userDTO);
            return Response.ok().build();
        } catch (Exception e) {
            throw new WebApplicationException(Response.status(401).
                    entity("Duplicate user ERROR! Exception:" + e).type("text/plain").build());
        }
    }

    @POST
    @Path("/authorize/")
    @Consumes(MediaType.APPLICATION_JSON)
    public String authorize(UserDTO userDTO) throws IOException {
        return factoryService.authorize(userDTO);
    }

    @GET
    @Path("/getUserTasks/{userId}/")
    @Produces(MediaType.APPLICATION_JSON)
    public UserTasksWrapper getUserTasks(@HeaderParam("name") String name, @HeaderParam("passwordHash") String passwordHash, @PathParam("userId") String userId) {
        String role = factoryService.authorize(new UserDTO(name, null, passwordHash, false, false));
        if (!role.equals("USER") && !role.equals("ADMIN")) {
            throw new WebApplicationException(Response.status(401).
                    entity("Non auhtorized!").type("text/plain").build());
        }
        return factoryService.getUserTasks(userId);
    }

    @GET
    @Path("/getAllUsers/")
    @Produces(MediaType.APPLICATION_JSON)
    public UsersWrapper getAllUsers(@HeaderParam("name") String name, @HeaderParam("passwordHash") String passwordHash) {
        String role = factoryService.authorize(new UserDTO(name, null, passwordHash, false, false));
        if (!role.equals("ADMIN")) {
            throw new WebApplicationException(Response.status(401).
                    entity("Non auhtorized!").type("text/plain").build());
        }
        return factoryService.getAllUsers();
    }

    @POST
    @Path("/updateUser/")
    @Consumes(MediaType.APPLICATION_JSON)
    public Response updateUser(@HeaderParam("name") String name, @HeaderParam("passwordHash") String passwordHash, UserDTO userDTO) throws IOException {
        String role = factoryService.authorize(new UserDTO(name, null, passwordHash, false, false));
        if (!role.equals("ADMIN")) {
            throw new WebApplicationException(Response.status(401).
                    entity("Non auhtorized!").type("text/plain").build());
        }
        factoryService.updateUser(userDTO);
        return Response.ok().build();
    }

    @GET
    @Path("/pay/{inputId}/")
    @Produces(MediaType.APPLICATION_JSON)
    public String pay(@HeaderParam("name") String name, @HeaderParam("passwordHash") String passwordHash, @PathParam("inputId") String inputId) {
        String role = factoryService.authorize(new UserDTO(name, null, passwordHash, false, false));
        if (!role.equals("USER") && !role.equals("ADMIN")) {
            throw new WebApplicationException(Response.status(401).
                    entity("Non auhtorized!").type("text/plain").build());
        }
        return "Not supported yet.";
    }

    @GET
    @Path("/paymentConfirmation/{inputId}/")
    @Produces(MediaType.APPLICATION_JSON)
    public String paymentConfirmation(@HeaderParam("name") String name, @HeaderParam("passwordHash") String passwordHash, @PathParam("inputId") String inputId) {
        String role = factoryService.authorize(new UserDTO(name, null, passwordHash, false, false));
        if (!role.equals("USER") && !role.equals("ADMIN")) {
            throw new WebApplicationException(Response.status(401).
                    entity("Non auhtorized!").type("text/plain").build());
        }
        return "Not supported yet.";
    }

    @GET
    @Path("/getStats/")
    @Produces(MediaType.APPLICATION_JSON)
    public Stats getStats(@HeaderParam("name") String name, @HeaderParam("passwordHash") String passwordHash) {
        String role = factoryService.authorize(new UserDTO(name, null, passwordHash, false, false));
        if (!role.equals("ADMIN")) {
            throw new WebApplicationException(Response.status(401).
                    entity("Non auhtorized!").type("text/plain").build());
        }

        Stats stats = factoryService.getStats();
        return stats;
    }
}
